﻿using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.Helpers;
using com.IronOne.BoardPACWinApp.Sync;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppService.Auth;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using Windows.UI.Xaml;
using com.IronOne.BoardPACWinAppUtil.Enums;

namespace com.IronOne.BoardPACWinApp.ViewModel.UserControlViewModel
{
    /// <summary>
    ///     This class contains properties that a View can data bind to.
    ///     <para>
    ///         See http://www.galasoft.ch/mvvm
    ///     </para>
    /// </summary>
    public class ProfileUserControlViewModel : ViewModelBase
    {
        /// <summary>
        ///     The <see cref="CanExecute" /> property's name.
        /// </summary>
        public const string CanExecutePropertyName = "CanExecute";

        public static bool IsUserInvolved;
        private bool _canExecute = true;
        private RelayCommand _userOnlineStatusChange;
        private readonly IAuthService _authService;
        private DispatcherTimer _dispatcherTimer;
        TimeSpan maxOfflineLoginIntervalInMin;

        /// <summary>
        ///     Initializes a new instance of the ProfileUserControlViewModel class.
        /// </summary>
        public ProfileUserControlViewModel()
        {
            _authService = new AuthService();
            Messenger.Default.Register<NotificationMessage<MessageDataModel>>(this, HandleMessages);
            GetProfileDataModel();
            _dispatcherTimer = new DispatcherTimer();
            _dispatcherTimer.Tick += (s, args) => DispatcherTimer_Tick();
        }

        /// <summary>
        ///     Sets and gets the CanExecute property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public bool CanExecute
        {
            get { return _canExecute; }

            set
            {
                if (_canExecute == value)
                {
                    return;
                }

                _canExecute = value;
                RaisePropertyChanged(CanExecutePropertyName);
            }
        }

        /// <summary>
        ///     Gets the UserOnlineStatusChange.
        /// </summary>
        public RelayCommand UserOnlineStatusChange
        {
            get
            {
                return _userOnlineStatusChange
                       ?? (_userOnlineStatusChange = new RelayCommand(
                           async () =>
                           {
                               try
                               {
                                   var isOnline = !(Convert.ToBoolean(_profileDataModel.ButtonTag));
                                   if (isOnline)
                                   {
                                       _profileDataModel.ButtonTag = true;
                                       _profileDataModel.UserOnlineStatus = "Online";
                                       _profileDataModel.OnlineStatusColor = "LightGreen";
                                       Global.UserForceWentOffline = false;

                                       IsUserInvolved = false;
                                       await NetworkConnectivityManager.ServerUpCheckOnce();

                                       await UpdateTimer(false);

                                       await Task.Delay(2000);
                                       SyncManager.GetInstance().StartSync();                                       
                                   }
                                   else
                                   {
                                       IsUserInvolved = true;
                                       SyncManager.StopSync();

                                       CanExecute = false;
                                       _profileDataModel.ButtonTag = false;
                                       _profileDataModel.UserOnlineStatus = "Pending";
                                       _profileDataModel.OnlineStatusColor = "Yellow";
                                       Global.UserForceWentOffline = true;

                                       var x = 0;
                                       while (true)
                                       {
                                           await Task.Delay(500);
                                           if (!SyncManager.IsSyncStopped())
                                           {
                                               x++;
                                               if (x == 1)
                                                   _profileDataModel.UserOnlineStatus = "Pending.";
                                               if (x == 2)
                                                   _profileDataModel.UserOnlineStatus = "Pending..";
                                               if (x == 3)
                                                   _profileDataModel.UserOnlineStatus = "Pending...";
                                               if (x != 1 && x != 2 && x != 3)
                                               {
                                                   _profileDataModel.UserOnlineStatus = "Pending";
                                                   x = 0;
                                               }
                                               continue;
                                           }
                                           CanExecute = true;
                                           _profileDataModel.ButtonTag = false;
                                           _profileDataModel.UserOnlineStatus = "Offline";
                                           _profileDataModel.OnlineStatusColor = "Gray";
                                           Global.UserForceWentOffline = true;
                                           break;
                                       }

                                       await UpdateTimer(true);
                                   }
                               }
                               catch (Exception)
                               {
                                   CanExecute = true;
                                   _profileDataModel.ButtonTag = false;
                                   _profileDataModel.UserOnlineStatus = "Offline";
                                   _profileDataModel.OnlineStatusColor = "Gray";
                                   Global.UserForceWentOffline = true;
                               }
                           }));
            }
        }

        protected async void HandleMessages(NotificationMessage<MessageDataModel> mdm)
        {
            try
            {
                if (mdm.Notification.Equals(MessageCodes.IS_ONLINE))
                {
                    if (IsUserInvolved) return;
                    var isOnline = (bool) mdm.Content.MessageData;

                    if (isOnline && !Global.UserForceWentOffline)
                    {
                        if (_profileDataModel == null) return;
                        if (_profileDataModel.ButtonTag) return;

                        _profileDataModel.ButtonTag = true;
                        _profileDataModel.UserOnlineStatus = "Online";
                        _profileDataModel.OnlineStatusColor = "LightGreen";

                        SyncManager.GetInstance().StartSync();
                    }
                    else
                    {
                        if (_profileDataModel == null) return;
                        _profileDataModel.ButtonTag = false;
                        _profileDataModel.UserOnlineStatus = "Offline";
                        _profileDataModel.OnlineStatusColor = "Gray";

                        SyncManager.StopSync();
                    }
                }

                if (mdm.Notification.Equals(MessageCodes.SYNC_ERROR_STOP))
                {
                    if (_profileDataModel == null) return;
                    _profileDataModel.ButtonTag = false;
                    _profileDataModel.UserOnlineStatus = "Offline";
                    _profileDataModel.OnlineStatusColor = "Gray";

                    Global.UserForceWentOffline = true;
                }

                if (mdm.Notification.Equals(MessageCodes.SYNC_DATA_DOWNLOAD_SUCCESS))
                {
                    await
                        CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                            GetProfileDataModel);
                }
            }
            catch (Exception)
            {
                if (_profileDataModel == null) return;
                _profileDataModel.ButtonTag = false;
                _profileDataModel.UserOnlineStatus = "Offline";
                _profileDataModel.OnlineStatusColor = "Gray";

                Global.UserForceWentOffline = true;
            }
        }

        private async void GetProfileDataModel()
        {
            var pdm = new ProfileDataModel();
            try
            {
                var um = await _authService.GetUserFromId();
                if (um == null) return;

                Global.IPadDisplayName = um.IPadDisplayName;
                pdm.ProfilePicPath = await BasePage.UpdateProfilePic(um.UserId);
                                
                if (Global.IsOnline && !Global.UserForceWentOffline)
                {
                    pdm.ButtonTag = true;
                    pdm.UserOnlineStatus = "Online";
                    pdm.OnlineStatusColor = "LightGreen";
                }
                else
                {
                    pdm.ButtonTag = false;
                    pdm.UserOnlineStatus = "Offline";
                    pdm.OnlineStatusColor = "Gray";
                }

                pdm.DisplayName = um.IPadDisplayName.Replace(" ", "\n");
                ProfileDataModel = pdm;

                if (Global.IsOnline && !Global.UserForceWentOffline) await UpdateTimer(false);
                else await UpdateTimer(true);
            }
            catch (Exception)
            {
            }
        }

        #region ProfileDataModel

        /// <summary>
        ///     The <see cref="ProfileDataModel" /> property's name.
        /// </summary>
        public const string ProfileDataModelPropertyName = "ProfileDataModel";

        private ProfileDataModel _profileDataModel;

        /// <summary>
        ///     Sets and gets the ProfileDataModel property.
        ///     Changes to that property's value raise the PropertyChanged event.
        /// </summary>
        public ProfileDataModel ProfileDataModel
        {
            get { return _profileDataModel; }

            set
            {
                if (_profileDataModel == value)
                {
                    return;
                }

                _profileDataModel = value;
                RaisePropertyChanged(ProfileDataModelPropertyName);
            }
        }

        #endregion

        private async Task UpdateTimer(bool isDisplay)
        {
            try
            {
                if (isDisplay)
                {
                    var maxOfflineLoginInterval = await _authService.GetSettingValueBySettingName(DatabaseType.UserDb, ApplicationConstants.UserDbSettingNames.MaxOfflineLoginInterval);
                    int val = Convert.ToInt32(maxOfflineLoginInterval);
                    maxOfflineLoginIntervalInMin = new TimeSpan(0, val, 0);
                    
                    _dispatcherTimer.Stop();                    
                    _dispatcherTimer.Interval = new TimeSpan(0, 0, 1); //1 second
                    _dispatcherTimer.Start();

                    _profileDataModel.OfflineTimerVisibility = Visibility.Visible;
                }
                else
                {
                    _profileDataModel.OfflineTimerVisibility = Visibility.Collapsed;
                    _profileDataModel.OfflineTimer = "";
                    _dispatcherTimer.Stop();
                }
            }
            catch (Exception)
            {
            }
        }

        private void DispatcherTimer_Tick()
        {
            try
            {
                if (maxOfflineLoginIntervalInMin.TotalHours == 0 && maxOfflineLoginIntervalInMin.TotalMinutes == 0 &&
                    maxOfflineLoginIntervalInMin.TotalSeconds == 0)
                {
                    _profileDataModel.OfflineTimer = "";
                    _profileDataModel.OfflineTimerVisibility = Visibility.Collapsed;

                    _dispatcherTimer.Stop();

                    var mdm = new MessageDataModel { MessageData = "Your offline time is out" };
                    var message = new NotificationMessage<MessageDataModel>(mdm, MessageCodes.SESSION_TIMEOUT_NOTIFY_TO_UI);
                    Messenger.Default.Send(message);
                    
                    return;
                }

                string dispTxt = "";
                if(maxOfflineLoginIntervalInMin.Hours > 0)
                    dispTxt = maxOfflineLoginIntervalInMin.Hours.ToString("0") + ":" + maxOfflineLoginIntervalInMin.Minutes.ToString("0") + ":" + maxOfflineLoginIntervalInMin.Seconds.ToString("00");
                else
                    dispTxt = maxOfflineLoginIntervalInMin.Minutes.ToString("0") + ":" + maxOfflineLoginIntervalInMin.Seconds.ToString("00");

                _profileDataModel.OfflineTimer = dispTxt;

                maxOfflineLoginIntervalInMin = maxOfflineLoginIntervalInMin.Subtract(new TimeSpan(0, 0, 1));
            }
            catch (Exception)
            {
            }
        }
    }
}